package top.bug.blog.utils;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import top.bug.blog.constant.CommonConstants;
import top.bug.blog.exception.BussinessException;

import java.util.Map;

/**
 * @author <a href="https://github.com/jiusi66">九思.</a>
 * @email 10837907@qq.com
 * @from <a href="https://www.52bug.top">递归茶馆-www.52bug.top</a>
 * @description MyBatis Plus 查询条件工具类
 */
public class QueryWrapperUtils {

    /**
     * 添加时间范围查询条件
     *
     * @param wrapper    查询包装器
     * @param timeRange  时间范围数组
     * @param timeColumn 时间字段引用
     * @param <T>        实体类型
     */
    public static <T> void addTimeRangeCondition(LambdaQueryWrapper<T> wrapper, String[] timeRange, SFunction<T, ?> timeColumn) {
        if (isValidTimeRange(timeRange)) {
            wrapper.between(timeColumn, timeRange[0], timeRange[1]);
        }
    }

    /**
     * 添加安全排序条件
     *
     * @param wrapper       查询包装器
     * @param sortField     前端传入的排序字段名
     * @param sortOrder     排序方向
     * @param fieldMap      允许排序的字段白名单
     * @param defaultColumn 默认排序字段
     * @param <T>           实体类型
     */
    public static <T> void addSafeSort(LambdaQueryWrapper<T> wrapper, String sortField, String sortOrder,
                                       Map<String, SFunction<T, ?>> fieldMap) {
        if (StrUtil.isBlank(sortField)) {
            return;
        }

        SFunction<T, ?> column = fieldMap.get(sortField);
        if (column == null) {
            throw new BussinessException("非法的排序字段: " + sortField);
        }

        boolean isAsc = CommonConstants.SORT_ORDER_ASC.equalsIgnoreCase(sortOrder);
        if (isAsc) {
            wrapper.orderByAsc(column);
        } else {
            wrapper.orderByDesc(column);
        }
    }

    /**
     * 校验时间范围参数有效性
     */
    private static boolean isValidTimeRange(String[] timeRange) {
        return ArrayUtil.isNotEmpty(timeRange)
                && timeRange.length == 2
                && StrUtil.isNotBlank(timeRange[0])
                && StrUtil.isNotBlank(timeRange[1]);
    }
}